package it.avantsoft.ls.peer;

import it.avantsoft.ls.base.Protocol;
import it.avantsoft.ls.peer.command.*;
import org.apache.log4j.Logger;

import java.io.DataInputStream;
import java.io.IOException;

public class PeerCommandFactory implements Protocol {
    private static Logger log = Logger.getLogger(ReceiverCommandFromGL.class);

    /**
     * getCommand reads the messageId and the messageLenght (in bytes) from the stream, then it creates
     * a command using these informations.
     *
     * @param input       The communication DataInputStream
     * @param peerHandler Peer Handler
     * @param commandByte Command
     * @return PeerCommand The command created after parsing input.
     */
    public static PeerCommand getCommand(PeerHandler peerHandler, byte commandByte, DataInputStream input) {
        PeerCommand command = null;
        try {
            switch (commandByte) {
                case NEW_CHILD:
                    String childId = input.readUTF();
                    command = new NewChildCommand(peerHandler, childId);
                    break;
                case CONNECT_TO:
                    childId = input.readUTF();
                    String groupLeaderHost = input.readUTF();
                    int groupLeaderListeningPort = input.readInt();
                    command = new ConnectToGLCommand(peerHandler, childId, groupLeaderHost, groupLeaderListeningPort);
                    break;
                case ADDRESS_BOOK:
                    String groupLeaderId = input.readUTF();
                    childId = input.readUTF();
                    byte abNumber = input.readByte();
                    int abID = input.readInt();//identificativo del tipo di addressbook
                    int length = input.readInt();
                    byte[] labByteArray = new byte[length];
                    input.readFully(labByteArray);
                    if (abNumber == (byte) 2) {
                        int abID2 = input.readInt();//identificativo del tipo di addressbook
                        length = input.readInt();
                        byte[] cabByteArray = new byte[length];
                        input.readFully(cabByteArray);
                        command = new ABCommand(peerHandler, groupLeaderId, childId, abID, labByteArray, abID2, cabByteArray);
                    } else {
                        command = new ABCommand(peerHandler, groupLeaderId, childId, abID, labByteArray);
                    }
                    break;
                case PONG:
                    command = new PongCommand(peerHandler);
                    break;
                case RETRY_CONNECTION:
                    //TODO RETRY_CONNECTION

                    break;
                case HORIZONTAL_BALANCE:
                    int loadDifference = input.readInt();
                    String designedGroupLeaderId = input.readUTF();
                    command = new HorizontalBalanceCommand(peerHandler, loadDifference, designedGroupLeaderId);
                    break;
                case NEWBROTHER:
                    String id = input.readUTF();
                    int port = input.readInt();
                    command = new NewBrotherABCommand(peerHandler, id, port);
                    break;
                case NEWNIECE:
                    //todo check
                    id = input.readUTF();
                    //port = input.readInt();
                    command = new NewNieceABCommand(peerHandler, id);
                    break;

                case DEADUNCLE:
                    id = input.readUTF();
                    command = new DeadUncleABCommand(peerHandler, id);
                    break;
                case DEADBROTHER:
                    id = input.readUTF();
                    command = new DeadBrotherABCommand(peerHandler, id);
                    break;
                case DEADNIECE:
                    id = input.readUTF();
                    command = new DeadNieceABCommand(peerHandler, id);
                    break;
                case ACKHORIZONTALBALANCEMESSAGE:
                    String exchangeablePeer = input.readUTF();
                    String designedGroupLeaderHost = input.readUTF();
                    int designedGroupLeaderListeningPort = input.readInt();
                    command = new ExecuteHorizontalBalanceCommand(peerHandler, exchangeablePeer, designedGroupLeaderHost, designedGroupLeaderListeningPort);
                    break;
            }
        } catch (IOException e) {
            log.error("Command Factory", e);
        }

        return command;
    }
}
